/**
 * Jaxson ajax
 *
 * Copyright Remedy Interactive, licensed under Apache version 2 license:
 *
 *  http://www.apache.org/licenses/LICENSE-2.0.html
 *
 * This notice must remain in all java source files.
 */
package org.jaxson.struts.upload;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.Properties;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jaxson.config.ApplicationConfiguration;
import org.jaxson.struts.BaseAction;
import org.jaxson.struts.reverseAjax.ReverseAjaxEvent;
import org.jaxson.struts.reverseAjax.ReverseAjaxManager;

import com.opensymphony.xwork2.interceptor.annotations.Before;

/**
 * @author Joe Maisel
 */
public class BaseUploadAction extends BaseAction
{
	private File upload;
	private String uploadContentType; 
	private String uploadFileName; 
	private String fileCaption;
	private String userDirectory;
	private boolean error;
	private boolean generalError;
	int maxFileSize = Integer.MAX_VALUE;
	
	private static final Log lager = LogFactory.getLog( BaseUploadAction.class );
	public static final String UPLOAD_IN_PROGRESS = BaseUploadAction.class.getName() + ".uploading";
	
	public BaseUploadAction()
	{
		try
		{
			Properties defaults = new Properties();
			defaults.load(  this.getClass().getClassLoader().getResourceAsStream( "org/apache/struts2/default.properties" ) );
			maxFileSize = Integer.parseInt( defaults.getProperty( "struts.multipart.maxSize" ) );
			
			InputStream is = this.getClass().getClassLoader().getResourceAsStream( "struts.properties" );
			if( is != null )
			{
				Properties overrides = new Properties();
				overrides.load( is );
				maxFileSize = Integer.parseInt( overrides.getProperty( "struts.multipart.maxSize" ) );
			}
		}
		catch( IOException e )
		{
			e.printStackTrace();
		}
	}
	
	@Before
	public void checkFileSize()
	{
		lager.info( upload );
	}
	
	/**
	 * @see org.jaxson.struts.BaseAction#handle()
	 */
	@Override
	public String handle()
	{
		ApplicationConfiguration conf = null;
		
		try
		{
			conf = ApplicationConfiguration.getInstance();
		}
		catch( IOException e )
		{
			e.printStackTrace();
		}
		
		File basedir = new File( conf.getProperty( "server.file.upload.dir" ) + File.separator + session.getId() );
		
		if( upload != null )
		{
			lager.debug( "upload not null" );
			
			SimpleDateFormat sdf = new SimpleDateFormat("yyMMdd");
			String ts = sdf.format( new Date() );
			
			if( !basedir.exists() )
				basedir.mkdirs();
			
			File output = new File( basedir, ts + "_" + getUploadFileName() );
			upload.renameTo( output );
		}
		
		if( error )
		{
			// notify that the file is too large
			ReverseAjaxEvent evt = new ReverseAjaxEvent();
			evt.setName( "upload.failed.file.size" );
			ReverseAjaxManager.sendImmediately( session, evt );
			
			return "input";
		}
		if( generalError )
		{
			// notify that the file is too large
			ReverseAjaxEvent evt = new ReverseAjaxEvent();
			evt.setName( "upload.failed.general" );
			ReverseAjaxManager.sendImmediately( session, evt );
			
			return "input";
		}
		
		session.removeAttribute( UPLOAD_IN_PROGRESS );
		return upload==null?"input":"success";
	}
	
	@Override
	public void validate()
	{
		lager.debug( "validate called: " + request + " " + request.getContentLength() );
		
		Collection<?> tmp = getActionErrors();
		Collection<String> errors = new ArrayList<String>();
		
		if( request.getContentLength() > 0 && request.getContentLength() >= getMaxFileSize() )
		{
			errors.add( "the request was rejected because its size" );
		}
		
		for( Object o : tmp )
		{
			lager.debug( this.getClass() + " : error > " + o.toString() );
			
			if( o.toString().contains( "the request was rejected because its size" ) )
			{
				lager.debug( "uploaded file too large! ----" + o.toString() );
				error = true;
			}
			else
			{
				lager.debug( "general error: ----" + o.toString() );
				generalError = true;
			}
		}
		
		session.removeAttribute( UPLOAD_IN_PROGRESS );
		setActionErrors( errors );
	}
	
	/**
	 * @see org.jaxson.struts.BaseAction#setServletRequest(javax.servlet.http.HttpServletRequest)
	 */
	@Override
	public void setServletRequest( HttpServletRequest request )
	{
		super.setServletRequest( request );
		session.setAttribute( UPLOAD_IN_PROGRESS, true );
	}

	/**
	 * @return the userDirectory
	 */
	public String getUserDirectory()
	{
		return this.userDirectory == null ? session.getId() : this.userDirectory;
	}

	/**
	 * @param userDirectory the userDirectory to set
	 */
	public void setUserDirectory( String userDirectory )
	{
		this.userDirectory = userDirectory;
	}

	/**
	 * @return the upload
	 */
	public File getUpload()
	{
		return upload;
	}

	/**
	 * @param upload the upload to set
	 */
	public void setUpload( File upload )
	{
		this.upload = upload;
	}

	/**
	 * @return the uploadContentType
	 */
	public String getUploadContentType()
	{
		return uploadContentType;
	}

	/**
	 * @param uploadContentType the uploadContentType to set
	 */
	public void setUploadContentType( String uploadContentType )
	{
		this.uploadContentType = uploadContentType;
	}

	/**
	 * @return the uploadFileName
	 */
	public String getUploadFileName()
	{
		return uploadFileName;
	}

	/**
	 * @param uploadFileName the uploadFileName to set
	 */
	public void setUploadFileName( String uploadFileName )
	{
		this.uploadFileName = uploadFileName;
	}

	/**
	 * @return the fileCaption
	 */
	public String getFileCaption()
	{
		return fileCaption;
	}

	/**
	 * @param fileCaption the fileCaption to set
	 */
	public void setFileCaption( String fileCaption )
	{
		this.fileCaption = fileCaption;
	}
	
	/**
	 * @return the maxFileSize
	 */
	public int getMaxFileSize()
	{
		return maxFileSize;
	}

	private static final long serialVersionUID = 1940931259641228567L;
}
